package edu.xidian.forum.controller;

import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import edu.xidian.forum.common.Result;
import edu.xidian.forum.dto.LoginDto;
import edu.xidian.forum.dto.RegisterDto;
import edu.xidian.forum.entity.Post;
import edu.xidian.forum.entity.User;
import edu.xidian.forum.service.PostService;
import edu.xidian.forum.service.UserService;
import edu.xidian.forum.util.MD5Utils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static edu.xidian.forum.jwt.JwtUtil.USER_NAME;

@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;
    @Resource
    private PostService postService;

    @Value("${avatar.storage}")
    private String avatarStorage;

    @PostMapping("/register")
    private Result<Void> register(@Valid @RequestBody RegisterDto registerDto) {
        return userService.executeRegister(registerDto);
    }

    @PostMapping("/login")
    private Result<String> login(@Valid @RequestBody LoginDto loginDto) {
        return userService.executeLogin(loginDto);
    }

    @GetMapping("/info")
    private Result<User> getInfo(@RequestHeader(value = USER_NAME) String username) {
        return Result.success(userService.getUserToFrontend(username));
    }

    /**
     * 检查密码是否匹配
     */
    @GetMapping("/checkUserPassword")
    public Result<Object> checkUserPassword(@RequestHeader(value = USER_NAME) String username,
                                            @RequestParam("oldPassword") String oldPassword) {
        User user = userService.getUser(username);
        if (ObjectUtils.isEmpty(user)) {
            return Result.failed("The user does not exist");
        }
        if (!MD5Utils.getPwd(oldPassword).equals(user.getPassword())) {
            return Result.failed("Wrong password");
        } else return Result.success();
    }

    @PostMapping("/updatePassword")
    public Result<Object> updatePassword(@RequestHeader(value = USER_NAME) String username,
                                         @RequestParam("oldPassword") String oldPassword,
                                         @RequestParam("newPassword") String newPassword) {
        User user = userService.getUser(username);
        if (ObjectUtils.isEmpty(user)) {
            return Result.failed("The user does not exist");
        }
        if (!MD5Utils.getPwd(oldPassword).equals(user.getPassword())) {
            return Result.failed("Wrong password");
        } else {
            user.setPassword(MD5Utils.getPwd(newPassword));
            userService.updateById(user);
            return Result.success("Password successfully changed", null);
        }
    }

    @PostMapping("/updateEmail")
    public Result<Object> updateEmail(@RequestHeader(value = USER_NAME) String username,
                                      @RequestParam("email") String email) {
        User check_user = userService.checkEmail(email);
        if (check_user != null)
            return Result.failed("The email was repeated");
        User user = userService.getUser(username);
        user.setEmail(email);
        userService.updateById(user);
        return Result.success();
    }

    @GetMapping("/{username}")
    public Result<Map<String, Object>> getUserByName(@PathVariable("username") String username,
                                                     @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
                                                     @RequestParam(value = "size", defaultValue = "10") Integer size) {
        Map<String, Object> map = new HashMap<>(16);
        User user = userService.getUserToFrontend(username);
        if (ObjectUtils.isEmpty(user)) {
            return Result.failed("The user does not exist");
        }
        Page<Post> page = postService.page(new Page<>(pageNo, size),
                Wrappers.<Post>lambdaQuery().eq(Post::getUserId, user.getId()));
        map.put("user", user);
        map.put("topics", page);
        return Result.success(map);
    }

    @PostMapping("/update")
    public Result<User> updateUser(@RequestBody User User) {
        userService.updateById(User);
        return Result.success(User);
    }

    @PostMapping("/upload_avatar")
    public Result<Object> uploadAvatar(@RequestHeader(value = USER_NAME) String userName,
                                       @RequestParam("file") MultipartFile file) throws IOException {
        String fileExtensionName = getFileSuffixFromContentType(file.getContentType());
        String newFileName = DigestUtil.sha1Hex(file.getInputStream()) + fileExtensionName;

        User user = userService.getUser(userName);

        String oldFileName = user.getAvatar();
        if (newFileName.equals(oldFileName)) {
            return Result.success(userService.getUserToFrontend(userName).getAvatar());
        }

        File newFile = new File(avatarStorage, newFileName);
        file.transferTo(newFile);

        user.setAvatar(newFileName);
        userService.updateById(user);
        return Result.success(userService.getUserToFrontend(userName).getAvatar());
    }


    @GetMapping("/logout")
    public Result<Object> logout() {
        return Result.success("Successfully log out", null);
    }

    private String getFileSuffixFromContentType(String contentType) {
        switch (contentType) {
            case "image/jpeg":
            case "application/x-jpg":
                return ".jpg";
            case "image/png":
                return ".png";
            case "image/gif":
                return ".gif";
            case "application/x-bmp":
                return ".bmp";
            default:
                return null;
        }
    }
}
